package cn.cj.erp.common.excel.excel;

import cn.cj.erp.common.excel.anno.Excel;
import cn.cj.erp.common.excel.enums.ExcelType;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.DecimalFormat;
import java.util.*;

/**
 * Excel处理对象
 *
 * @author jianchen
 */
@Slf4j
@Data
public class ExcelBean<T> {
    /** 数字格式 */
    private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00");

    /** 工作表名称 */
    private String sheetName;

    /** 导出类型（EXPORT:导出数据；IMPORT：导入模板） */
    private ExcelType type;

    /** 工作薄对象 */
    private Workbook wb;

    /** 工作表对象 */
    private Sheet sheet;

    /** 样式列表 */
    private Map<String, CellStyle> styles;

    /** 导入导出数据列表 */
    private List<T> list;

    /** 注解字段列表 */
    private List<Object[]> fields;

    /** 当前行号 */
    private int rowNum;

    /** 标题 */
    private String title;

    /** 最大高度 */
    private short maxHeight;

    /** 合并后最后行数 */
    private int subMergedLastRowNum = 0;

    /** 合并后开始行数 */
    private int subMergedFirstRowNum = 1;

    /** 对象的子列表方法 */
    private Method subMethod;

    /** 对象的子列表属性 */
    private List<Field> subFields;

    /** 统计列值 */
    private final Map<Integer, Double> statistics = new HashMap<>();

    /** 实体对象 */
    private Class<T> clazz;

    /** 需要排除列属性 */
    private String[] excludeFields;

    public ExcelBean(Class<T> clazz) {
        this.clazz = clazz;
    }

    public ExcelBean(Class<T> clazz, String[] excludeFields) {
        this.clazz = clazz;
        if (!ArrayUtil.isEmpty(excludeFields)) {
            this.excludeFields = excludeFields;
        }
    }

    public CellStyle getCellStyle(String key) {
        return styles.get(key);
    }

    /**
     * 是否有对象的子列表
     */
    public boolean hasSubList() {
        return subFields != null && subFields.size() > 0;
    }

    /**
     * 是否有对象的子列表，集合不为空
     */
    public boolean hasSubList(Object obj) {
        return hasSubList() && CollectionUtil.isNotEmpty(getSubListValue(obj));
    }

    /**
     * 获取子类值
     */
    public Collection<?> getSubListValue(Object obj) {
        Object value;
        try {
            value = subMethod.invoke(obj);
        } catch (Exception e) {
            return new ArrayList<>();
        }
        return (Collection<?>) value;
    }

    /**
     * 创建工作表
     *
     * @param sheetNo sheet数量
     * @param index   序号
     */
    public void createSheet(int sheetNo, int index) {
        // 设置工作表的名称.
        if (sheetNo > 1 && index > 0) {
            this.sheet = wb.createSheet();
            this.createTitle();
            wb.setSheetName(index, sheetName + index);
        }
    }

    /**
     * 创建excel标题
     */
    public void createTitle() {
        if (StrUtil.isNotEmpty(this.title)) {
            this.subMergedFirstRowNum++;
            this.subMergedLastRowNum++;
            int titleLastCol = this.fields.size() - 1;
            if (this.hasSubList()) {
                titleLastCol = titleLastCol + this.subFields.size() - 1;
            }
            Row titleRow = this.sheet.createRow(this.rowNum == 0 ? this.rowNum++ : 0);
            titleRow.setHeightInPoints(30);
            Cell titleCell = titleRow.createCell(0);
            titleCell.setCellStyle(this.getCellStyle("title"));
            titleCell.setCellValue(this.title);
            CellRangeAddress rangeAddress = new CellRangeAddress(titleRow.getRowNum(),
                    titleRow.getRowNum(), titleRow.getRowNum(), titleLastCol);
            this.sheet.addMergedRegion(rangeAddress);
        }
    }

    /**
     * 创建单元格
     */
    public void createHeadCell(Excel attr, Row row, int column) {
        // 创建列
        Cell cell = row.createCell(column);
        // 写入列信息
        cell.setCellValue(attr.name());
        PoiUtil.createSelectBox(wb, sheet, attr, column);

        cell.setCellStyle(this.getCellStyle(ExcelFieldHandler.getHeadStyleKey(attr)));
        if (hasSubList()) {
            // 填充默认样式，防止合并单元格样式失效
            sheet.setDefaultColumnStyle(column, this.getCellStyle(ExcelFieldHandler.getDataStyleKey(attr)));
            if (attr.needMerge()) {
                sheet.addMergedRegion(new CellRangeAddress(rowNum - 1, rowNum, column, column));
            }
        }
    }

    /**
     * 创建统计行
     */
    public void createStatRow() {
        if (statistics.size() > 0) {
            Row row = sheet.createRow(sheet.getLastRowNum() + 1);
            Set<Integer> keys = statistics.keySet();
            Cell cell = row.createCell(0);
            cell.setCellStyle(styles.get("total"));
            cell.setCellValue("合计");

            for (Integer key : keys) {
                cell = row.createCell(key);
                cell.setCellStyle(styles.get("total"));
                cell.setCellValue(DOUBLE_FORMAT.format(statistics.get(key)));
            }
            statistics.clear();
        }
    }

    /**
     * 合计统计信息
     */
    public void statData(Integer index, String text, boolean enabled) {
        if (!enabled) {
            return;
        }
        Double temp = 0D;
        if (!statistics.containsKey(index)) {
            statistics.put(index, temp);
        }
        try {
            temp = Double.valueOf(text);
        } catch (NumberFormatException e) {
            log.error("addStatisticsData 转double异常", e);
        }
        statistics.put(index, statistics.get(index) + temp);
    }
}